package com.example.performance.r2dbc.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zpMeng
 * @since 6/25/2025
 */
public class PerformanceCollector {

    public static void printSerial(Map<? extends Number, List<Double>> map) {
        for (Map.Entry<? extends Number, List<Double>> entry : map.entrySet()) {
            Number nodeSize = entry.getKey();
            Double average = getAverage(entry.getValue());

            System.out.println(entry.getValue());
            System.out.println("nodeSize: %d -- avg duration: %f".formatted(nodeSize, average));
        }
    }

    public static void printParallel(int concurrency,
                                     List<Double> parallelPerformance,
                                     Map<Long, List<Double>> map) {
        Double totalAverage = getAverage(parallelPerformance);

        Long nodeSize = map.keySet().stream().findFirst().orElseThrow();
        List<Double> threadDurations = map.get(nodeSize);
        Double threadAverage = getAverage(threadDurations);

        System.out.println(parallelPerformance);
        System.out.printf("""
                        concurrency: %d  test count: %d
                        total duration: %f each thread performance: %f
                        """,
                concurrency, threadDurations.size(), totalAverage, threadAverage);

    }

    public static Double getAverage(List<Double> durations) {

        if (durations.size() > 1) {
            Double max = durations.stream().reduce(Double::max).orElseThrow();
            durations.remove(max);
        }

        Double total = durations.stream()
                .reduce(Double::sum)
                .orElseThrow();
        return total / durations.size();
    }


    public static void printParallel(List<Double> totalDurations, int concurrency) {
        System.out.println(totalDurations);
        Double avgDuration = PerformanceCollector.getAverage(totalDurations);
        System.out.printf("concurrency: [%d] -- total count: [%d] -- avg duration: [%f]%n",
                concurrency, totalDurations.size(), avgDuration);
    }
}
